"""BrowserAutomation类 - 提供浏览器自动化功能"""

import time
from typing import List, Dict, Any, Optional, Tuple, Union
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import (
    NoSuchElementException,
    ElementClickInterceptedException,
    TimeoutException,
    WebDriverException
)
from rpa_framework.rpa_logging.logger import Logger
from rpa_framework.exceptions.rpa_exceptions import (
    ElementNotFoundException,
    BrowserAutomationException as BrowserOperationException,
    TimeoutException
)
from rpa_framework.utils.browser_driver_manager import BrowserDriverManager

class BrowserAutomation:
    """浏览器自动化类，基于Selenium实现网页操作"""
    
    def __init__(self, headless: bool = False):
        """初始化浏览器自动化
        
        Args:
            headless: 是否使用无头模式
        """
        self.logger = Logger("BrowserAutomation")
        self.driver = None
        self.headless = headless
        # 初始化驱动管理器
        self.driver_manager = BrowserDriverManager()
        self.initialize_driver()
    
    def initialize_driver(self) -> None:
        """初始化WebDriver"""
        try:
            options = Options()
            
            if self.headless:
                options.add_argument('--headless')
                self.logger.debug("使用无头模式启动浏览器")
            
            # 添加一些常用配置
            options.add_argument('--no-sandbox')
            options.add_argument('--disable-dev-shm-usage')
            options.add_argument('--start-maximized')
            options.add_argument('--ignore-certificate-errors')
            
            self.logger.info("正在初始化Chrome浏览器")
            
            # 检查并确保驱动已安装
            if not self.driver_manager.check_driver_installed('chrome'):
                self.logger.warning("Chrome驱动未安装，正在尝试安装...")
                success = self.driver_manager.download_driver('chrome')
                if not success:
                    raise BrowserOperationException("无法安装Chrome驱动")
            
            # 获取驱动路径并初始化
            driver_path = self.driver_manager.get_driver_path('chrome')
            if not driver_path:
                raise BrowserOperationException("无法找到Chrome驱动")
                
            self.driver = webdriver.Chrome(
                service=Service(driver_path),
                options=options
            )
            
            # 设置隐式等待时间
            self.driver.implicitly_wait(10)
            self.logger.info("浏览器初始化成功")
            
        except Exception as e:
            self.logger.error(f"浏览器初始化失败: {str(e)}")
            raise BrowserOperationException(f"无法启动浏览器: {str(e)}") from e
    
    def navigate(self, url: str) -> None:
        """导航到指定URL
        
        Args:
            url: 要访问的网址
        """
        self.logger.info(f"导航到: {url}")
        
        try:
            self.driver.get(url)
        except Exception as e:
            self.logger.error(f"导航失败: {str(e)}")
            raise BrowserOperationException(f"无法导航到URL: {str(e)}") from e
    
    def find_element(self, by: str, value: str, timeout: int = 10) -> webdriver.remote.webelement.WebElement:
        """查找元素
        
        Args:
            by: 定位方式 (id, name, xpath, css_selector, class_name, tag_name, link_text, partial_link_text)
            value: 定位值
            timeout: 超时时间（秒）
            
        Returns:
            找到的元素
            
        Raises:
            ElementNotFoundException: 未找到元素
        """
        self.logger.debug(f"查找元素: {by}={value}")
        
        try:
            element = WebDriverWait(self.driver, timeout).until(
                EC.presence_of_element_located((getattr(By, by.upper()), value))
            )
            return element
        except TimeoutException:
            self.logger.error(f"未找到元素: {by}={value}")
            raise ElementNotFoundException(f"未找到元素: {by}={value}")
    
    def find_elements(self, by: str, value: str, timeout: int = 10) -> List[webdriver.remote.webelement.WebElement]:
        """查找多个元素
        
        Args:
            by: 定位方式
            value: 定位值
            timeout: 超时时间（秒）
            
        Returns:
            找到的元素列表
        """
        self.logger.debug(f"查找多个元素: {by}={value}")
        
        try:
            elements = WebDriverWait(self.driver, timeout).until(
                EC.presence_of_all_elements_located((getattr(By, by.upper()), value))
            )
            return elements
        except TimeoutException:
            self.logger.warning(f"未找到任何元素: {by}={value}")
            return []
    
    def click_element(self, by: str, value: str, timeout: int = 10) -> None:
        """点击元素
        
        Args:
            by: 定位方式
            value: 定位值
            timeout: 超时时间（秒）
        """
        self.logger.debug(f"点击元素: {by}={value}")
        
        try:
            element = WebDriverWait(self.driver, timeout).until(
                EC.element_to_be_clickable((getattr(By, by.upper()), value))
            )
            element.click()
        except (TimeoutException, ElementClickInterceptedException) as e:
            self.logger.error(f"点击元素失败: {by}={value}, 错误: {str(e)}")
            # 尝试使用JavaScript点击
            try:
                element = self.find_element(by, value, timeout)
                self.driver.execute_script("arguments[0].click();", element)
                self.logger.debug(f"使用JavaScript点击成功: {by}={value}")
            except Exception as js_error:
                raise BrowserOperationException(f"无法点击元素: {str(js_error)}") from js_error
    
    def input_text(self, by: str, value: str, text: str, clear_first: bool = True, timeout: int = 10) -> None:
        """在输入框中输入文本
        
        Args:
            by: 定位方式
            value: 定位值
            text: 要输入的文本
            clear_first: 是否先清空输入框
            timeout: 超时时间（秒）
        """
        self.logger.debug(f"在元素 {by}={value} 中输入文本: {text}")
        
        try:
            element = self.find_element(by, value, timeout)
            
            if clear_first:
                element.clear()
            
            element.send_keys(text)
        except Exception as e:
            self.logger.error(f"输入文本失败: {str(e)}")
            raise BrowserOperationException(f"无法输入文本: {str(e)}") from e
    
    def get_text(self, by: str, value: str, timeout: int = 10) -> str:
        """获取元素文本
        
        Args:
            by: 定位方式
            value: 定位值
            timeout: 超时时间（秒）
            
        Returns:
            元素的文本内容
        """
        element = self.find_element(by, value, timeout)
        text = element.text
        self.logger.debug(f"获取元素文本: {by}={value}, 文本: {text}")
        return text
    
    def get_attribute(self, by: str, value: str, attribute: str, timeout: int = 10) -> str:
        """获取元素属性值
        
        Args:
            by: 定位方式
            value: 定位值
            attribute: 属性名
            timeout: 超时时间（秒）
            
        Returns:
            属性值
        """
        element = self.find_element(by, value, timeout)
        attr_value = element.get_attribute(attribute)
        self.logger.debug(f"获取元素属性: {by}={value}, 属性: {attribute}, 值: {attr_value}")
        return attr_value
    
    def wait_for_element(self, by: str, value: str, timeout: int = 30) -> webdriver.remote.webelement.WebElement:
        """等待元素出现
        
        Args:
            by: 定位方式
            value: 定位值
            timeout: 超时时间（秒）
            
        Returns:
            找到的元素
        """
        self.logger.debug(f"等待元素出现: {by}={value}, 超时: {timeout}秒")
        return self.find_element(by, value, timeout)
    
    def wait_for_element_disappear(self, by: str, value: str, timeout: int = 30) -> bool:
        """等待元素消失
        
        Args:
            by: 定位方式
            value: 定位值
            timeout: 超时时间（秒）
            
        Returns:
            元素消失返回True，超时返回False
        """
        self.logger.debug(f"等待元素消失: {by}={value}, 超时: {timeout}秒")
        
        try:
            WebDriverWait(self.driver, timeout).until(
                EC.invisibility_of_element_located((getattr(By, by.upper()), value))
            )
            return True
        except TimeoutException:
            self.logger.warning(f"元素未消失: {by}={value}")
            return False
    
    def wait_for_page_load(self, timeout: int = 30) -> bool:
        """等待页面加载完成
        
        Args:
            timeout: 超时时间（秒）
            
        Returns:
            页面加载完成返回True，超时返回False
        """
        self.logger.debug(f"等待页面加载完成，超时: {timeout}秒")
        
        try:
            WebDriverWait(self.driver, timeout).until(
                lambda d: d.execute_script('return document.readyState') == 'complete'
            )
            return True
        except TimeoutException:
            self.logger.warning("页面加载超时")
            return False
    
    def switch_to_frame(self, frame_reference: Union[str, int, webdriver.remote.webelement.WebElement], timeout: int = 10) -> None:
        """切换到iframe
        
        Args:
            frame_reference: frame名称、索引或元素
            timeout: 超时时间（秒）
        """
        self.logger.debug(f"切换到iframe: {frame_reference}")
        
        try:
            WebDriverWait(self.driver, timeout).until(
                EC.frame_to_be_available_and_switch_to_it(frame_reference)
            )
        except TimeoutException:
            self.logger.error(f"无法切换到iframe: {frame_reference}")
            raise BrowserOperationException(f"切换iframe失败")
    
    def switch_to_default_content(self) -> None:
        """切换回主文档"""
        self.driver.switch_to.default_content()
        self.logger.debug("切换回主文档")
    
    def scroll_to_element(self, by: str, value: str, timeout: int = 10) -> None:
        """滚动到指定元素
        
        Args:
            by: 定位方式
            value: 定位值
            timeout: 超时时间（秒）
        """
        element = self.find_element(by, value, timeout)
        self.driver.execute_script("arguments[0].scrollIntoView({behavior: 'smooth'});", element)
        self.logger.debug(f"滚动到元素: {by}={value}")
    
    def take_screenshot(self, filename: str = "browser_screenshot.png") -> None:
        """截取浏览器屏幕
        
        Args:
            filename: 保存文件名
        """
        self.driver.save_screenshot(filename)
        self.logger.debug(f"浏览器截图已保存: {filename}")
    
    def get_current_url(self) -> str:
        """获取当前URL
        
        Returns:
            当前页面的URL
        """
        url = self.driver.current_url
        self.logger.debug(f"当前URL: {url}")
        return url
    
    def get_title(self) -> str:
        """获取页面标题
        
        Returns:
            页面标题
        """
        title = self.driver.title
        self.logger.debug(f"页面标题: {title}")
        return title
    
    def refresh(self) -> None:
        """刷新页面"""
        self.driver.refresh()
        self.logger.debug("刷新页面")
    
    def back(self) -> None:
        """返回上一页"""
        self.driver.back()
        self.logger.debug("返回上一页")
    
    def forward(self) -> None:
        """前进到下一页"""
        self.driver.forward()
        self.logger.debug("前进到下一页")
    
    def execute_javascript(self, script: str, *args) -> Any:
        """执行JavaScript代码
        
        Args:
            script: JavaScript代码
            *args: 参数
            
        Returns:
            JavaScript执行结果
        """
        self.logger.debug(f"执行JavaScript: {script}")
        return self.driver.execute_script(script, *args)
    
    def quit(self) -> None:
        """关闭浏览器并退出WebDriver"""
        if self.driver:
            self.logger.info("关闭浏览器")
            self.driver.quit()
            self.driver = None
    
    def __del__(self):
        """析构函数，确保浏览器被关闭"""
        self.quit()

if __name__ == "__main__":
    # 示例用法
    browser = BrowserAutomation(headless=False)
    try:
        browser.navigate("https://www.baidu.com")
        browser.input_text("id", "kw", "RPA自动化")
        browser.click_element("id", "su")
        browser.wait_for_page_load()
        browser.take_screenshot("baidu_search.png")
    finally:
        browser.quit()